/*
 * TacticaDemo01.java
 *
 * Created on 16 de julio de 2006, 13:20
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package futbol.tacticas.concursantes.TacticaQBitMExhicoByZeru;


import futbol.General;
import futbol.tacticas.Comando;
import futbol.tacticas.ComandoGolpearBola;
import futbol.tacticas.ComandoIrA;
import futbol.tacticas.ComandoPase;
import futbol.tacticas.ComandoTiroAPuerta;
import futbol.tacticas.SituacionJugadores;
import futbol.tacticas.concursantes.Tactica;
import java.awt.Color;
import java.awt.Point;

import java.util.Random;
import java.util.RandomAccess;
import java.util.Vector;

import java.lang.Math;


/**
 *
 * @author Administrador
 */
public class TacticaQBitMExhicoByZeru implements Tactica{
    
	Point BalonAnt;
	
    private int nValores[][]={
        {160,60,7},		//	  Delantero
        {160,70,5}, 	// 2
        {160,60,4},
        {-160,0, 4}, 	// 4  Portero    
        {160,-60,4},
        {30,20,4},	// 6
        {160,60,4},
        {160,50,4},		// 8
        {160,-60,7},	//    Delantero
        {160,00,7},		// 10 Delantero
        {30,-20,4},
                  
    };
    
    private int nAreaVariable[];
    private int nArea[][]={
            {80, -60, 3},	//	  Delantero
            {-110,-30,3},  	// 2
            {-102,-40,3},
            {-155, 0, 2},    // 4  Portero  
            {-30,-40, 3},
            {0,  60, 8},  	// 6
            {30, 0, 3},
            {10, 10, 3},	// 8
            {80, 60, 3},	//    Delantero
            {50, 0, 3},	// 10 Delantero
            {-110,30, 3}
    };
    
    private Point Fantasma;
    
    
    private int MARCA[];
    private Point posAntEnemigo[];
    private double velEnemigo[];
    
    
    public TacticaQBitMExhicoByZeru() {
    	
    	nAreaVariable = new int[11];
    	MARCA = new int[11];
    	posAntEnemigo = new Point[11];
    	for (int n=0;n<11;n++){
    		posAntEnemigo[n] = new Point();
    	}
    	velEnemigo = new double[11];
    	
    	
    	Fantasma = new Point();
      	BalonAnt = new Point();
      	
    	Inicializa();
    	
    }
    
    /*
    protected void finalize() throws Throwable
    {
    	for (int n=0;n<11;n++){
    		System.out.println("[" + n + "]:" + velEnemigo[n]);
    	}    
    }*/
    
    private void Inicializa()
    {
    	Fantasma.setLocation(-170, -100);
    	limpiaMarcas();
    }

    private void limpiaMarcas ()
    {
    	for (int n=0;n<11;n++){
    		MARCA[n] = -1;
    		nAreaVariable[n] = nArea[n][2];
    	}
    	MARCA[4-1] = -2; 	// Portero
    	MARCA[1-1] = -2; 	// Delantero
    	MARCA[6-1] = -2; 	// Delantero
    	MARCA[10-1] = -2; 	// Delantero
    	MARCA[9-1] = -2; 	// Delantero
    	

    }
    
    public String getNombre(){
        return "QBitMexhico by Zeru";
    }
    
    public Color getColor1(){
        return Color.WHITE;
    }
    
    public Color getColor2(){
        return new Color(255,128,0);
    }
    
    public Color getColorNumero(){
        return Color.black;
    }
    
    public int getFuerza(int n){
        return nValores[n][2];
    }
    public int getXInicial(int n){
        return nValores[n][0];
    }
    
    public int getYInicial(int n){
        return nValores[n][1];
    }
    
    private int zonaMuerta[]={0,0,0,0,5,15,55,107}; // Esto se lo copiamos a pathetics
    
    public Vector<Comando> getComandos(SituacionJugadores sj){
    
    	Vector<Comando> comandos=new Vector();
    	Point bola=sj.getBola();
    	
    	CalculaVelocidadesEnemigo(sj);
    	AsignaMarca(sj);
    	
    	
    	if (Math.abs(bola.getX()) >= 159) {
    		Inicializa();
    	}
    		
    	// SAQUE -->>
		if ((bola.distance(0,0) == 0) && 
			(sj.getMisJugadores()[11-1].distance(0,0)==0)) {
			comandos.add(new ComandoGolpearBola(11-1, -160, 0));
		}
        // SAQUE <<--
    	
    	for (int n=0;n<11;n++) {
    		
    		
            // MOVER -->>
    		if (BolaEnArea(n, sj) ) {
    			Point IrA = PredecirCaidaDeLaBola(sj, n);
    			comandos.add(new ComandoIrA(n, IrA.getX(), IrA.getY()));
    		} else {	
    			comandos.add(Marcaje(n, sj));
     		}
    		// MOVER <<--
    		
    		
    		// PATEAR -->>
    		    		
    		if (sj.getMisJugadores()[n].distance(bola) < 10) {
    			
    			if (sj.getMisJugadores()[n].distance(160,0) > (zonaMuerta[getFuerza(n)]+20)) {
    				
    				Point Juga;
    				
    				if (bola.distance(-165, 0) < 30) {
    					if (bola.getY()>0) { 
    						Juga = new Point(-130, 120);
    					} else { 
    						Juga = new Point(-130, -120);
    					}
    				} else {
    					Juga = MejorLugarParaPase(n, sj);
    					comandos.add(new ComandoIrA(n, Juga.getX(), Juga.getY()));
    				}
					  					
					comandos.add(PaseMejorao(n, Juga, sj));
 		
    			} else {				
    				
    				comandos.add(new ComandoTiroAPuerta(n, 0));
    				
    			}
			}
    		// PATEAR <<--
    		
    		
    		

    		
    	}
    
    	BalonAnt.setLocation(sj.getBola());
    	
    
    	ActualizaFantasma(sj);
    	return comandos;
    	
    }
       
    void CalculaVelocidadesEnemigo(SituacionJugadores sj)
    {
    	
    	Point bola=sj.getBola();

    	for (int n=0;n<11;n++) {
    		if (bola.distance(0, 0) > 1) {
    			double vel = posAntEnemigo[n].distance(sj.getContrario()[n]);
    			if (vel > velEnemigo[n]) {
    				velEnemigo[n] = vel;
    			}
    			//System.out.println("[" + n + "]:" + velEnemigo[n]);
    		}
    		posAntEnemigo[n] = sj.getContrario()[n]; 
    	}
    }
    
    void ActualizaFantasma(SituacionJugadores sj)
    {
    	Point bola=sj.getBola();
    	double Dist = bola.distance(Fantasma);
		double x = (bola.getX() - Fantasma.getX()) / Dist;
    	double y = (bola.getY() - Fantasma.getY()) / Dist;
    	Fantasma.setLocation(Fantasma.getX() + x*3, Fantasma.getY() + y*5); // 3 , 5
    }
    
    ComandoIrA Marcaje(int Uno, SituacionJugadores sj)
    {
			if (MARCA[Uno] > -1) {
				Point Juga = sj.getContrario()[MARCA[Uno]];
				
				Point bola=sj.getBola();
				double Dist = bola.distance(Juga);
				
				double x = (bola.getX() - Juga.getX()) / Dist;
		    	double y = (bola.getY() - Juga.getY()) / Dist;
				return new ComandoIrA(Uno, Juga.getX() + 21*x, Juga.getY() + 21*y); //20
			}		
			return new ComandoIrA(Uno, nArea[Uno][0], nArea[Uno][1]);		
    }
    
    void AsignaMarca(SituacionJugadores sj)
    {

    	
    	limpiaMarcas();
    	
    	int n = EnemigoMasCercanoDesmarcado(sj);
    	while (n != -1 ) {
    		int i = MioMasCercaSinMarca(n, sj);
    		if (i != -1) {
    			nAreaVariable[i] = 0;
    			MARCA[i] = n;
    		} else {
    			break;
    		}
    		n = EnemigoMasCercanoDesmarcado(sj);
    	}
    	
    }
    
    int EnemigoMasCercanoDesmarcado (SituacionJugadores sj) 
    {
    	
    	double dis = sj.getContrario()[sj.getContrarioMasCerca(-160, 0)].distance(-160, 0);
    	int DisMar = 200; //200
    	if (dis < 70) DisMar = 150; // 100/130
    	
    	
    	int Jug = -1;
    	
    	double DisMin = 999;
    	for (int n=0;n<11;n++) {
    		if (velEnemigo[n] < 6.5) { // 5
	    		double Dis = sj.getContrario()[n].distance(-160, 0);
	    		if (Dis < DisMar) {
					if (Dis < DisMin) {
		    			if (!EnemigoMarcado(n)) {
		    				DisMin = Dis;
		    				Jug = n;
		    			}
					}
	    		}
    		}
    	}
    	return Jug;
    }

    boolean EnemigoMarcado(int n)
    {
		boolean YaAsignado = false;
		for (int i=0;i<11;i++) {
			if (MARCA[i] == n)
			{
				YaAsignado = true;
				break;
			}
		}
		return YaAsignado;
    }
    	
    int MioMasCercaSinMarca (int n, SituacionJugadores sj) {
    	double DisMin = 999;
    	int Jug = -1;
    	for (int i=0;i<11;i++) {
    		if (MARCA[i] == -1) {
				double Dis = sj.getContrario()[n].distance(sj.getMisJugadores()[i]);
				if (Dis < DisMin) {
					DisMin = Dis;
					Jug = i;
				}
    		}
    	}
    	return Jug;
    }
    
    Comando PaseMejorao(int Uno, Point punto, SituacionJugadores sj)
    {   
    	
    	Point bola=sj.getBola();
    	
    	double x = (punto.getX() - bola.getX())/* / bola.distance(punto)*/;
    	double y = (punto.getY() - bola.getY())/* / bola.distance(punto)*/;
    	
    	double Fac = 5.6/nValores[Uno][2] - 0.4;
    	
    	if (sj.getMisJugadores()[Uno].distance(sj.getContrario()[sj.getContrarioMasCerca(bola.getX(), bola.getY())]) < 20)
    	{
    		return new ComandoGolpearBola(Uno, bola.getX()+x*1.8*Fac, bola.getY()+y*1.8*Fac);   // ?
    		//return new ComandoTiroAPuerta(Uno, 0);
    		//return new ComandoPase(Uno, sj.getSiguienteJugador(Uno));
    		//return new ComandoPase(Uno, Uno);
    		
    	} else {
    		return new ComandoGolpearBola(Uno, bola.getX()+x*0.9*Fac, bola.getY()+y*0.9*Fac);	//0.9
    	}
    	
    }
    
    double DistanciaEntreJugadores(int Uno, int Dos, SituacionJugadores sj) {
    	return General.getDistancia(sj.getMisJugadores()[Uno].getX(),
				 sj.getMisJugadores()[Uno].getY(),
				 sj.getMisJugadores()[Dos].getX(),
				 sj.getMisJugadores()[Dos].getY());
    }
    
    double JugadorPelota(int Uno, SituacionJugadores sj) {
    	Point bola=sj.getBola();
    	return General.getDistancia(sj.getMisJugadores()[Uno].getX(),
				 sj.getMisJugadores()[Uno].getY(),
				 bola.getX(),
				 bola.getY());
    }
    
    boolean BolaEnArea(int Uno, SituacionJugadores sj) {
    	
    	if (sj.getMasCercanoDeBola() == Uno) {
    		//MARCA[Uno] = -1;
    		if (MARCA[Uno] < 0) {
    			return true;
    		}
    	}
    	 	
    	Point bola=sj.getBola();
    	if (General.getDistancia(
    			 nArea[Uno][0],
    			 nArea[Uno][1],
				 bola.getX(),
				 bola.getY()) < (nAreaVariable[Uno]/10.0) * 320){
    		return true;
    	} else {
    		return false;
    	}
    }

    Point PredecirPosicionBola(SituacionJugadores sj, int futuro) 
    {
    	Point bola=sj.getBola();
    	
    	double VelocidadActualX = bola.getX() - BalonAnt.getX();
    	double VelocidadActualY = bola.getY() - BalonAnt.getY();
    	double Velocidad = Math.sqrt((VelocidadActualX*VelocidadActualX) + (VelocidadActualY*VelocidadActualY));
    	
    	double VelocidadEnFuturo = Velocidad;
    	
    	if (Velocidad != 0) {
    	
	    	Point bolaEnFuturo = new Point();
	    	double bolaEnFuturoX = bola.getX();
	    	double bolaEnFuturoY = bola.getY();
	    	for (int i = 0; i < futuro; i++) {
	    		
	    		bolaEnFuturoX = bolaEnFuturoX + (VelocidadActualX - i*VelocidadActualX/Velocidad);
	    		bolaEnFuturoY = bolaEnFuturoY + (VelocidadActualY - i*VelocidadActualY/Velocidad);
	    		
	    		VelocidadEnFuturo = Math.sqrt(Math.pow(i*VelocidadActualY/Velocidad, 2) + Math.pow(i*VelocidadActualY/Velocidad, 2));  
	    	}
	    	
	    	if (bolaEnFuturoX < -160) bolaEnFuturoX = - 160 + (-bolaEnFuturoX-160);
	    	if (bolaEnFuturoX >  160) bolaEnFuturoX = + 160 - (+bolaEnFuturoX-160);
	    	
	    	if (bolaEnFuturoY < -120) bolaEnFuturoY = - 120 + (-bolaEnFuturoY-120);
	    	if (bolaEnFuturoY >  120) bolaEnFuturoY = + 120 - (+bolaEnFuturoY-120);
	    
	    	if (VelocidadEnFuturo >= 15) bolaEnFuturoX = -999;
	    	
	    	bolaEnFuturo.setLocation(bolaEnFuturoX, bolaEnFuturoY);
	    
	    	return bolaEnFuturo;
    	} else {
    		return bola;
    	}
    	
    	
    }
    
    Point PredecirPosicionJugador(SituacionJugadores sj, int futuro, int Uno, Point Destino) 
    {
    	int velocidad = 10-nValores[Uno][2];
    	double x = sj.getMisJugadores()[Uno].getX();
    	double y = sj.getMisJugadores()[Uno].getY();
    	for (int i = 0; i < futuro; i++) {
	        if (General.getDistancia(x,y,Destino.getX(),Destino.getY())>velocidad){
	            double angulo=General.getAngulo(x,y,Destino.getX(),Destino.getY());
	            x+=Math.cos(angulo)*velocidad;
	            y+=Math.sin(angulo)*velocidad;
	        }else{
	            x=Destino.getX();
	            y=Destino.getY();
	        }
    	}
    	Point Resultado = new Point();
    	Resultado.setLocation(x, y);
    	return Resultado;
    }
    
    Point PredecirCaidaDeLaBola(SituacionJugadores sj, int Uno)
    {
    	
    	int iMejor = 0;
    	for (int i=0; i<30; i++)
    	{
    		Point bola = PredecirPosicionBola(sj, i);
    		Point Jug = PredecirPosicionJugador(sj, i, Uno, bola);
    		
    		double Distancia = Jug.distance(bola);
    		
    		if (Distancia < 10) {
    			iMejor = i;
    			break;
    		}
    	}
    	
    	return PredecirPosicionBola(sj, iMejor);
    }
    
    Point MejorLugarParaPase(int Uno, SituacionJugadores sj)
    {
    	Point mejorPunto = new Point();
    	double Mejor = -9999;
    	
    	
    	for (int j=0; j<11; j++) {
    		if (Uno != j) {
    			if (sj.getMisJugadores()[j].distance(160,0) < (zonaMuerta[getFuerza(j)]+20)) {
    				if (DistanciaEntreJugadores(Uno, j, sj) < 40) {
    					return sj.getMisJugadores()[j];
    				}
    			}
    		}
		}
    	
    	
    	for (int x = -160; x < 160; x=x+1)
    	{
    		for (int y = -120; y < 120; y=y+1)
        	{
    	    			
    			if (sj.getMisJugadores()[Uno].distance(x,y) < 40) {
    				if (sj.getMisJugadores()[Uno].distance(x,y) >= 15) { // 15
    					
    					double MenorDistancia = 999;
	    				for (int j=0; j<11; j++) {
	    					double dis = sj.getContrario()[j].distance(x, y);
	    					if (dis < MenorDistancia)  MenorDistancia = dis;
	    				}
	    				
	    				
	    				double dis = Fantasma.distance(x, y);
	    				if (dis < MenorDistancia)  MenorDistancia = dis;

    					
        					
    					double DistanciaATiradores =  sj.getMisJugadores()[10-1].distance(x,y)+
							    					  sj.getMisJugadores()[9-1].distance(x,y)+ 
							    					  sj.getMisJugadores()[1-1].distance(x,y)+
							    					  5 * General.getDistancia(x, y, 165, 0);  
    					
    					DistanciaATiradores = DistanciaATiradores / 8.0; //8.0
    					    				
	    				MenorDistancia = MenorDistancia - DistanciaATiradores/4.0; // 3.0
	    				
    					if (MenorDistancia > Mejor) {
    						Mejor = MenorDistancia;
    						mejorPunto.setLocation(x,y);
    					}
	    				
    				}
    			}
        	}
    	}

    	return mejorPunto;
    }
    
    
    
    
}